/**
 * SessionHelper.java
 * @author: liuex
 * 2008-1-7 ����09:09:50
 *
 * note: 
 */
package org.lex.app.sessions;

import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.util.LinkedList;

import javax.swing.JSplitPane;

import org.lex.app.prefs.ResourceMap;
import org.lex.awt.ComponentUtilities;
import org.lex.awt.ComponentVisitor;
import org.lex.filter.Filter;
import org.lex.utils.Codec;
import org.lex.utils.functor.UnaryFunctor;


/*
 * NOT USED ANY MORE, USE SessionStorageHelper INSTEAD
 */
public class SessionHelper {
	private static final String BOUNDS = ".bounds";
	private static final String FRAME_STATE = ".state";
	private static final String FRAME_EXT_STATE = ".extstate";
	private static final String DIVIDER_LOCATION = ".divider.location";
	private static final String DIVIDER_SIZE = ".divider.size";
	// currently we just interest in Frame&Dialog,
	// will add JSplitPane, JTabbedPane etc. later.
	private static final Filter<Component> filter = new Filter<Component>() {
		public boolean accept(Component c) {
			if (c instanceof Frame)
				return true;
			if (c instanceof Dialog)
				return true;
			if (c instanceof JSplitPane)
				return true;
			return false;
		}
	};

	public static void save(final ResourceMap sessions, Component root) {
		long start = System.currentTimeMillis();
		ComponentVisitor.previsite(root, filter, new UnaryFunctor<Void, Component>() {
			private LinkedList<String> names = new LinkedList<String>();

			public Void operate(Component c) {
				if (names.contains(c.getName())) {
					System.err.println("ERROR: component name '" + c.getName() + "' already exists, you should choose another "
							+ "one, otherwise session-storage will act weird");
				}
				if (c instanceof Dialog)
					SessionHelper.saveDialog(sessions, c);
				else if (c instanceof Frame)
					SessionHelper.saveFrame(sessions, (Frame) c);
				else if (c instanceof JSplitPane)
					SessionHelper.saveSplitPane(sessions, (JSplitPane) c);
				return null;
			}
		});
		long time = System.currentTimeMillis() - start;
		System.out.println("saveing-session using: " + time + "ms");
	}

	public static void restore(final ResourceMap sessions, Component root) {
		long start = System.currentTimeMillis();
		ComponentVisitor.previsite(root, filter, new UnaryFunctor<Void, Component>() {
			public Void operate(Component c) {
				if (c instanceof Dialog)
					SessionHelper.restoreDialog(sessions, c);
				else if (c instanceof Frame)
					SessionHelper.restoreFrame(sessions, (Frame) c);
				else if (c instanceof JSplitPane)
					SessionHelper.restoreSplitPane(sessions, (JSplitPane) c);
				return null;
			}
		});
		long time = System.currentTimeMillis() - start;
		System.out.println("restore-session using: " + time + "ms");
	}

	private static void saveDialog(ResourceMap sessions, Component c) {
		if (false == checkNull(c))
			return;
		sessions.putString(c.getName() + BOUNDS, Codec.encodeRectangle(c.getBounds()));
	}

	private static void saveFrame(ResourceMap sessions, Frame frame) {
		saveDialog(sessions, frame);
		String name = frame.getName();
		sessions.putProperty(name + FRAME_STATE, frame.getState());
		sessions.putProperty(name + FRAME_EXT_STATE, frame.getExtendedState());
	}

	private static void saveSplitPane(ResourceMap sessions, JSplitPane pane) {
		if (false == checkNull(pane))
			return;
		sessions.putProperty(pane.getName() + DIVIDER_LOCATION, pane.getDividerLocation());
		sessions.putProperty(pane.getName() + DIVIDER_SIZE, pane.getDividerSize());
	}

	private static void restoreDialog(ResourceMap sessions, Component c) {
		if (false == checkNull(c))
			return;
		String name = c.getName() + BOUNDS;
		if (sessions.containsProperty(name))
			c.setBounds(Codec.decodeRectangle(sessions.getString(name)));
	}

	private static void restoreFrame(ResourceMap sessions, Frame frame) {
		restoreDialog(sessions, frame);
		String name = frame.getName();
		String key = name + FRAME_STATE;
		if (sessions.containsProperty(key))
			frame.setState(sessions.getInt(key));
		key = name + FRAME_EXT_STATE;
		if (sessions.containsProperty(key))
			frame.setExtendedState(sessions.getInt(key));
	}

	private static void restoreSplitPane(ResourceMap sessions, JSplitPane pane) {
		if (false == checkNull(pane))
			return;
		String name = pane.getName() + DIVIDER_LOCATION;
		if (sessions.containsProperty(name))
			pane.setDividerLocation(sessions.getInt(name));
		name = pane.getName() + DIVIDER_SIZE;
		if (sessions.containsProperty(name))
			pane.setDividerSize(sessions.getInt(name));
	}

	private static boolean checkNull(Component c) {
		if (null == c) {
			error("component can't be null");
			return false;
		}
		String name = c.getName();
		if (null == name) {
			error("component must have a non-null name for session-storage");
			ComponentUtilities.dumpComponent(c, System.err);
			return false;
		}
		name = name.trim();
		if (0 == name.length()) {
			error("component name(or after trim()) should be a non-empty string");
			ComponentUtilities.dumpComponent(c, System.err);
			return false;
		}
		return true;
	}

	private static void error(String msg) {
		System.err.println(msg);
	}

	private SessionHelper() {
	}
}
